

// -----------------------------------------------------------------------
//
// Public Get/Set
//
// -----------------------------------------------------------------------


template <typename T>
inline T IniFile::GetValue ( const std::string & sectionName, const std::string & optionName ) const
{
	auto option = GetOption( sectionName, optionName );
	return GetValue< T >( option.GetValues()[ 0 ] );
}


template <typename T>
inline std::vector< T > IniFile::GetValues (
	const std::string & sectionName,
	const std::string & optionName
) const
{
	auto option = GetOption( sectionName, optionName );

	vector< string > allValues;
	GetAllValues( option, allValues );

	// convert strings to type T:
	std::vector< T > finalValues;
	finalValues.reserve( allValues.size() );
	for ( size_t i = 0; i < allValues.size(); ++i )
	{
		finalValues.push_back( GetValue< T >( allValues[ i ] ) );
	}

	return finalValues;
}


template <typename T>
void IniFile::SetValue ( const std::string & sectionName, const std::string & optionName, const T & value )
{
	// convert value to string:
	std::stringstream ss;
	ss << value;
	std::vector< std::string > valuesStr;
	valuesStr.push_back( ss.str() );

	auto optionInfo = GetOptionType( sectionName, optionName );
	if ( !optionInfo->AreValuesValid( valuesStr, valuesStr.size() ) )
	{
		std::stringstream ss;
		ss << "value \"" << ss.str() << "\" is not valid for option \"" << optionName
			<< "\" from section \"" << sectionName << "\"";
		throw ExceptionIniLib( ss.str() );
	}

	// set value:
	auto & option = GetOption( sectionName, optionName );
	vector< string > vecVal;
	vecVal.push_back( ToString( value ) );
	option.SetValues( vecVal );
	ValidateReferences();
}


template <typename T>
void IniFile::SetValues (
	const std::string & sectionName,
	const std::string & optionName,
	const std::vector< T > & values
)
{
	std::stringstream ss;
	std::vector< std::string > valuesStr;
	for ( size_t i = 0; i < values.size(); ++i )
	{
		ss.clear();
		ss.str( "" );
		ss << values[ i ];
		valuesStr.push_back( ss.str() );
	}

	auto optionInfo = GetOptionType( sectionName, optionName );
	if ( !optionInfo->AreValuesValid( valuesStr, valuesStr.size() ) )
	{
		std::stringstream ss;
		ss << "value \"" << ss.str() << "\" is not valid for option \"" << optionName
			<< "\" from section \"" << sectionName << "\"";
		throw ExceptionIniLib( ss.str() );
	}

	// convert strings:
	std::vector< std::string > stringVec;
	stringVec.reserve( values.size() );
	for ( size_t i = 0; i < values.size(); ++i )
	{
		stringVec.push_back( ToString( values[ i ] ) );
	}

	// set values:
	auto & option = GetOption( sectionName, optionName );
	option.SetValues( stringVec );
	ValidateReferences();
}


// -----------------------------------------------------------------------
//
// Private Get/Set support methods
//
// -----------------------------------------------------------------------


template <typename T>
inline T IniFile::GetValue ( const std::string & value ) const
{
	std::stringstream ss( value );
	T result;

	inilib::operator>>( ss, result );
	return result;
}


template <typename T>
std::string IniFile::ToString ( const T & value ) const
{
	std::stringstream ss;
	ss << value;
	return ss.str();
}